package com.briup.es.service.impl;

import com.briup.es.config.auth.SecurityUserContext;
import com.briup.es.config.exception.ServiceException;
import com.briup.es.config.response.ResultCode;
import com.briup.es.domain.bean.Book;
import com.briup.es.domain.dto.BookChangeNumDTO;
import com.briup.es.domain.vo.BookDetailVO;
import com.briup.es.domain.vo.BookVO;
import com.briup.es.mapper.BookMapper;
import com.briup.es.service.BookService;
import com.briup.es.utils.BeanUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;

@Service
@RequiredArgsConstructor
public class BookServiceImpl implements BookService {

    private final BookMapper bookMapper;

    @Override
    public List<BookVO> showBooksLimit20() {
        List<Book> books = bookMapper.queryAll();
        // 随机获取前20本图书，用于模拟热门推荐的动态性，并返回数据
        List<Book> bookList = books.subList(0, Math.min(books.size(), 20));
        Collections.shuffle(bookList);
        // 进行bean转换并返回数据
        return BeanUtil.bean2VOS(bookList, BookVO.class);
    }

    @Override
    public List<BookVO> findByCategoryId(Integer categoryId) {
        List<Book> books = bookMapper.searchBookByConditional(categoryId, null);
        return BeanUtil.bean2VOS(books, BookVO.class);
    }

    @Override
    public List<BookVO> searchBook(String query) {
        List<Book> books = bookMapper.searchBookByConditional(null, query);
        return BeanUtil.bean2VOS(books, BookVO.class);
    }

    @Override
    public BookDetailVO queryBookDetailById(Integer bookId) {
        // 查询图书详细信息中包含 当前用户是否收藏的标识，所以需要获取当前登录用户的id
        Integer userId = SecurityUserContext.userId();
        return bookMapper.queryById(bookId, userId);
    }

    @Override
    @Transactional
    public void changeStoreNum(List<BookChangeNumDTO> dtoList) {
        // 修改图书库存之前，确保该图书还处于上架状态
        List<Integer> bookIds = dtoList.stream()
                .map(BookChangeNumDTO::getBookId).toList();
        // 遍历需要修改的数据，一一修改对应商品的库存
        for (BookChangeNumDTO bookChangeNumDTO : dtoList) {
            Book book = bookMapper.queryById2(bookChangeNumDTO.getBookId());
            Integer changeNum = bookChangeNumDTO.getChangeNum();
            // 图书为null 以及变化量为负数时，需要抛出异常；
            // 因为变化量为负数此时表示生成订单，如果图书不存在或已下架就无法生成订单
            if (book == null) {
                if (changeNum <= 0) {
                    throw new ServiceException(ResultCode.BOOK_IS_NOT_EXISTS);
                } else {
                    // 如果变化量为正数，表示取消订单时，将库存加回到商品库存中，
                    // 如果该商品不存在或已下架，那么无需修改，直接返回即可
                    return;
                }
            }else {
                // 如果book不为null，那么说明该图书商品存在并且还处于上架状态，那么生成订单时就需要确保该订单的库存足够
                // 计算商品变化后的库存
                book.setStoreNum(book.getStoreNum()+changeNum);
                // 确保生成订单时，商品的库存大于等于用户购买的商品数量
                if (book.getStoreNum()<0){
                    throw new ServiceException(ResultCode.BOOK_STORE_NUM_IS_NULL);
                }
            }
            // 在确保上述操作无误后，就可以修改图书商品的库存
            bookMapper.updateBookStoreNum(book.getId(),book.getStoreNum());
        }
    }
}
